package com.example.droolstool.service;

import com.example.droolstool.base.Constants;
import com.example.droolstool.filter.ServerAssembleAgendaFilter;
import com.example.droolstool.module.DrlMessageModule;
import com.example.droolstool.module.EdgeModule;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.drools.core.impl.InternalKnowledgeBase;
import org.drools.core.impl.KnowledgeBaseFactory;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Results;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.builder.KnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderError;
import org.kie.internal.builder.KnowledgeBuilderErrors;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.io.ResourceFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author 赵云龙
 * @Date 2020/6/26
 * @Description TODO
 */

@Service
public class ExecuteDrlAssembleServerImpl {

    ServerAssembleDrlListener serverAssembleDrlListener = new ServerAssembleDrlListener();



    public void executeDrl(String id) {
        String rules= Constants.drlMap.get(id);
        KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        //以DRL形式加载规则
        builder.add(ResourceFactory.newByteArrayResource(rules.getBytes()), ResourceType.DRL);
        KnowledgeBuilderErrors errors = builder.getErrors();
//        Results results = builder.getResults();
//        if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
//            System.out.println(results.getMessages());
//            throw new IllegalStateException("### errors ###");
//        }
        for (KnowledgeBuilderError error : errors) {
            System.out.println(error.getMessage());
        }
        InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
        kBase.addPackages(builder.getKnowledgePackages());
        //获取规则引擎会话session
        KieSession session = kBase.newKieSession();
        session.setGlobal("executedDrlIds", Lists.newArrayList(Constants.executedRuleId));
        session.setGlobal("endNoteId", Constants.endExecuteDrlIds);
        ServerAssembleAgendaFilter serverAssembleAgendaFilter = new ServerAssembleAgendaFilter();
        // todo    节点可以存储成一个缓存/数据库  这样不需要每次遍历原始数据
        Constants.startExecuteDrlIds.forEach(startExecuteDrlId ->{
            Constants.serverAssembleModule.getServiceNodeModules().forEach(serverNodeModule -> {
                if (StringUtils.equals(startExecuteDrlId, serverNodeModule.getId())){
                    //插入需匹配的对象
                    session.insert(serverNodeModule);
                    //执行规则
                    session.fireAllRules(serverAssembleAgendaFilter);
                    //释放资源
//                    session.dispose();
                }
            });
        });
    }


    public void ExeServerAssemble(DrlMessageModule drlMessageModule) {
        if (drlMessageModule != null) {
            if (StringUtils.equals(drlMessageModule.getType(),"1")) {//数据源
                executeDbSourceServer(drlMessageModule);
            } else if (StringUtils.equals(drlMessageModule.getType(), "2")) {//数据转换

            } else if (StringUtils.equals(drlMessageModule.getType(), "3")) {// 业务算法
                executeBusinessArithmeticServer(drlMessageModule);
            } else if (StringUtils.equals(drlMessageModule.getType(), "4")) {//数据输出
                executeDBxPort(drlMessageModule);
            }

//            executeDbConversion(drlMessageModule);//数据转换是线

            sendMessage(drlMessageModule);
        }
    }


    /**
     * 数据源服务调度
     */
    public void executeDbSourceServer(DrlMessageModule drlMessageModule) {

        //todo 模拟返回数据
        Map<String, Object> respondParam = Maps.newHashMap();
        respondParam.put("key1", "12");
        respondParam.put("key2", "13");
        drlMessageModule.setRespondParams(respondParam);
        serverAssembleDrlListener.ServerAssembleDrl(drlMessageModule);

    }

    /**
     * 执行数据转换服务调度
     *
     * @param drlMessageModule
     */
    public void executeDbConversion(DrlMessageModule drlMessageModule) {

        String currentId = drlMessageModule.getId();
        List<String> toId = drlMessageModule.getToId();
        if (!StringUtils.isEmpty(currentId) && toId != null && !CollectionUtils.isEmpty(toId)) {
            List<EdgeModule> edgeModules = Constants.serverAssembleModule.getEdgeModules();
            List<EdgeModule> executeEdgeModules = edgeModules.stream().filter(edgeModule ->
                    StringUtils.equals(currentId, edgeModule.getSource()) && toId.contains(edgeModule.getTarget())).collect(Collectors.toList());
            executeEdgeModules.forEach(edgeModule -> {
                //TODO  调度数据转换服务
                System.out.println("this is " + edgeModule.getId() + "的数据转换");
            });
        }


    }

    /**
     * 执行业务算法服务  服务调度
     *
     * @param drlMessageModule
     */
    public void executeBusinessArithmeticServer(DrlMessageModule drlMessageModule) {
        //todo 模拟返回数据
//        Map<String, Object> respondParam = Maps.newHashMap();
//        respondParam.put("key1", "12");
//        respondParam.put("key2", "13");
        drlMessageModule.setRespondParams(drlMessageModule.getRequestParams());
        serverAssembleDrlListener.ServerAssembleDrl(drlMessageModule);
    }

    /**
     * 执行数据导出服务调度
     *
     * @param drlMessageModule
     */
    public void executeDBxPort(DrlMessageModule drlMessageModule) {
        //todo 模拟返回数据
        drlMessageModule.setRespondParams(drlMessageModule.getRespondParams());
        serverAssembleDrlListener.ServerAssembleDrl(drlMessageModule);
    }

    /**
     * 发消息通知执行的状态
     *
     * @param drlMessageModule
     */
    private void sendMessage(DrlMessageModule drlMessageModule) {

    }

    /**
     * 记录日志
     */
    private void saveLog(DrlMessageModule drlMessageModule) {

    }

}
